package com.rajaev.dtu.tractor.domain.service;


import com.rajaev.dtu.tractor.app.service.RoleService;
import com.rajaev.dtu.tractor.domain.entity.RolePo;
import com.rajaev.dtu.tractor.domain.repository.mysql.ResourceDao;
import com.rajaev.dtu.tractor.domain.repository.mysql.RoleDao;
import com.rajaev.dtu.tractor.domain.repository.mysql.RoleResourceDao;
import com.rajaev.dtu.tractor.domain.repository.mysql.UserRoleDao;
import com.rajaev.dtu.tractor.domain.vo.ResourceVo;
import com.rajaev.dtu.tractor.domain.vo.RoleVo;
import com.rajaev.dtu.tractor.infrastructure.base.errors.BusinessException;
import com.rajaev.dtu.tractor.infrastructure.base.errors.ErrorCodes;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@CacheConfig(cacheNames = "roles")
public class RoleDomain implements RoleService {

    @Autowired
    private Mapper dozerMapper;

    @Autowired
    RoleResourceDao roleResourceDao;

    @Autowired
    UserRoleDao userRoleDao;

    @Autowired
    ResourceDao resourceDao;

    @Autowired
    private RoleDao roleDao;

    @Override
    @Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_UNCOMMITTED)
    @CacheEvict(allEntries = true)
    public void insertRole(RoleVo roleVo) throws BusinessException {

        if(roleDao.selectRoleByName(roleVo.getRoleName())!=null){
            throw new BusinessException(ErrorCodes.ERR_ROLE_HAS_EXIST);
        }

        RolePo rolePo = dozerMapper.map(roleVo,RolePo.class);
        roleDao.insertRole(rolePo);

        List<Integer> roleResourceIds = new ArrayList<>();
        roleVo.getResources().forEach(resourcePo -> roleResourceIds.add(resourcePo.getId()));
        roleResourceDao.insertRoleResources(roleResourceIds,rolePo.getId());
    }

    @Override
    @CacheEvict(allEntries = true)
    public void updateRole(RoleVo roleVo) throws BusinessException {
        RolePo originRole = roleDao.selectRoleById(roleVo.getId());
        //当角色名有修改时，需要判断修改后的角色名是否已经存在
        if(!roleVo.getRoleName().equalsIgnoreCase(originRole.getRoleName())){
            if(roleDao.selectRoleByName(roleVo.getRoleName())!=null){
                throw new BusinessException(ErrorCodes.ERR_ROLE_HAS_EXIST);
            }
            RolePo rolePo = dozerMapper.map(roleVo,RolePo.class);
            roleDao.updateRole(rolePo);
        }

        //修改角色的资源信息
        roleResourceDao.deleteRoleResourceByRoleId(roleVo.getId());

        List<Integer> roleResouceIds = new ArrayList<>();
        roleVo.getResources().forEach(resourcePo -> roleResouceIds.add(resourcePo.getId()));
        roleResourceDao.insertRoleResources(roleResouceIds,roleVo.getId());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(allEntries = true)
    public void deleteRole(Integer roleId) {

        //删除角色时，删除对应的角色
        userRoleDao.deleteUserRolesByRoleId(roleId);
        //删除角色
        roleDao.deleteRole(roleId);
        //删除角色对应的资源关系
        roleResourceDao.deleteRoleResourceByRoleId(roleId);
    }

    @Override
    @Cacheable
    public List<RoleVo> selectRoles() {
        List<RolePo> rolePos = roleDao.selectRoles();
        List<RoleVo>  vos = new ArrayList<>();
        for(RolePo rolePo : rolePos){
            RoleVo roleVo = new RoleVo();
            roleVo.setRoleName(rolePo.getRoleName());
            roleVo.setResources(rolePo.getResoucePoList());
            roleVo.setId(rolePo.getId());
            vos.add(roleVo);
        }
        return vos;
    }

    @Override
    public List<ResourceVo> selectAllResource() {
        return resourceDao.selectAllResource();
    }
}
